home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Base / ListTemplate.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-19  |  19.7 KB  |  661 lines  |  [TEXT/CWIE]

  1. #pragma once
  2.  
  3. #ifndef __LISTTEMPLATE__
  4. #define __LISTTEMPLATE__
  5.  
  6. #define DEBUGPREEMPTIVELOCK 1
  7.  
  8. //
  9. // For 'nil'
  10. //
  11. #include <Types.h>
  12.  
  13. //
  14. // This is how many elements our list grows by every time we run
  15. // out of space.  We could potentially be a lot more intelligent
  16. // about our growing behavior.
  17. //
  18. // n.b. Currently these lists never trim, which could be bad.
  19. //
  20. #define kAllocationChunk            32
  21.  
  22. //
  23. // We usually don't have more than two iterators on a list, so
  24. // we'll only allocate space for the iterator list two elements
  25. // at a time.
  26. //
  27. #define kIterListAllocationChunk    2
  28.  
  29. typedef Boolean (*ListElementCompareProcPtr)(const char* item1, const char* item2);
  30.  
  31.  
  32. class TAbstractListIterator;
  33.  
  34. //================================================================================
  35. // CLASS TListStorage
  36. //
  37. // This class is for use by the list template, and isn't intended for direct use.
  38. //================================================================================
  39.  
  40. class TListStorage
  41. {
  42.     //
  43.     // Only TAbstractListIterators may add or remove themselves
  44.     // to our iterator list
  45.     //
  46.     friend class TAbstractListIterator;
  47.     
  48. public:
  49.     TListStorage(UInt32 itemSize) :
  50.         fListData(nil),
  51.         fItemSize(itemSize),
  52.         fItemsInList(0),
  53.         fSpaceReserved(0),
  54. #if DEBUGPREEMPTIVELOCK
  55.         fReadLocks(0),
  56.         fWriteLocks(0),
  57. #endif
  58.         fIteratorList(nil),
  59.         fNumberOfIterators(0),
  60.         fIteratorListReservedSpace(0) {}
  61.     
  62.     TListStorage(UInt32 itemSize, UInt32 initialItemSpace) :
  63.         fListData(nil),
  64.         fItemSize(itemSize),
  65.         fItemsInList(0),
  66.         fSpaceReserved(0),
  67. #if DEBUGPREEMPTIVELOCK
  68.         fReadLocks(0),
  69.         fWriteLocks(0),
  70. #endif
  71.         fIteratorList(nil),
  72.         fNumberOfIterators(0),
  73.         fIteratorListReservedSpace(0) { this->InsureAdequateSpace(initialItemSpace); }
  74.     
  75.     TListStorage(const TListStorage& copyFrom);
  76.     
  77.     ~TListStorage();
  78.     
  79.     //
  80.     // Simple list access
  81.     //
  82.     Boolean                    Empty() const                                    { return (this->ItemsInList() == 0); }
  83.     UInt32                    ItemsInList() const                                { return fItemsInList; }
  84.  
  85.     //
  86.     // Primary list-manipulation and item access API:
  87.     //
  88.     TListStorage*            Clone() const;
  89.     
  90.     //
  91.     // Add an item to the list in no particular order (puts new
  92.     // item in using the fastest insertion available)
  93.     //
  94.     void                    Add(const char* elementAddress);
  95.     Boolean                    Remove(const char*, ListElementCompareProcPtr compareProc);
  96.     
  97.     //
  98.     // n.b.    Inserting N items at the beginning of the list is O(N^2)
  99.     //        Inserting N items at the end of the list is O(N)
  100.     //        Inserting N items at the end of the list and reversing their order is also O(N).
  101.     //    
  102.     void                    InsertAtBeginning(const char* elementAddress);
  103.     void                    InsertAtEnd(const char* elementAddress);
  104.  
  105.     //
  106.     // n.b.    Removing N items from the beginning of the list is O(N^2)
  107.     //        Removing N items from the end of the list is O(N)
  108.     //
  109.     void                    RemoveFromBeginning();
  110.     void                    RemoveFromEnd();
  111.  
  112.     //
  113.     // List accessors
  114.     //    
  115.     void                    FirstItem(char* copyToBuffer) const;
  116.     void                    LastItem(char* copyToBuffer) const;
  117.  
  118.     //
  119.     // Misc list manipulation
  120.     //
  121.     void                    ReverseOrderOfList(char* tempBuffer);
  122.     void                    MakeEmpty();
  123.  
  124.     //
  125.     // Access locks for preemptive software (see comment below)
  126.     //
  127.     void                    LockForReading() const;
  128.     void                    RelinquishReadLock() const;
  129.     void                    LockForWriting();
  130.     void                    RelinquishWriteLock();
  131.     
  132.     //
  133.     // Not preemptive-safe if called directly; however, ONLY
  134.     // these routines + the "simple list access" routines may
  135.     // be called if you explicitly lock a list for writing.
  136.     //
  137.     // If you explicitly lock a list for reading, it is okay
  138.     // to call 'const' routines from above, but don't call any
  139.     // routines that try to write, or you'll deadlock.
  140.     //
  141.     void                    ItemAtIndex(SInt32 itemIndex, char* copyToBuffer) const;
  142.     void                    ReplaceItemAtIndex(SInt32 itemIndex, const char* dataToReplaceWith);
  143.     void                    RemoveItemAtIndex(SInt32 itemIndex);
  144.     SInt32                    IndexOfItem(const char*, ListElementCompareProcPtr compareProc, SInt32 indexToStartAt = 0) const;
  145.         
  146. private:
  147.     
  148.     //
  149.     // Memory handling
  150.     //
  151.     void                    InsureAdequateSpace(SInt32 numberOfItems);
  152.     
  153.     //
  154.     // Peeking at items:
  155.     //
  156.     const char*                ItemAddress(SInt32 itemIndex)    const                { return this->fListData + (itemIndex * fItemSize); }
  157.     char*                    ItemAddress(SInt32 itemIndex)                        { return this->fListData + (itemIndex * fItemSize); }
  158.     
  159.     //
  160.     // Keeping iterators in sync:
  161.     //
  162.     void                    AddIterator(TAbstractListIterator*);
  163.     void                    RemoveIterator(TAbstractListIterator*);
  164.     void                    InsureSpaceForIteratorList(UInt16 numberOfItersNeeded);
  165.  
  166.     void                    NotifyItemAdded(SInt32 indexOfNewItem);
  167.     void                    NotifyItemRemoved(SInt32 indexOfItemRemoved);
  168.     void                    NotifyListDestroyed();
  169.     
  170. private:
  171.     char*                    fListData;
  172.     UInt32                    fItemSize;
  173.     UInt32                    fItemsInList;
  174.     UInt32                    fSpaceReserved;
  175.  
  176. #if DEBUGPREEMPTIVELOCK
  177.     UInt32                    fReadLocks;
  178.     UInt32                    fWriteLocks;
  179. #endif
  180.     
  181.     TAbstractListIterator**    fIteratorList;
  182.     UInt16                    fNumberOfIterators;
  183.     UInt16                    fIteratorListReservedSpace;
  184. };
  185.  
  186. template <class T> class AnIteratorOfAListOf;
  187.  
  188. //================================================================================
  189. // TEMPLATE AListOf
  190. //================================================================================
  191.  
  192. template <class T> class AListOf
  193. {
  194.     //
  195.     // This is only here so that the iterator can gain access to the
  196.     // list storage object durring its constructor and destructor,
  197.     // and thereby register itself with the list storage.
  198.     //
  199.     friend class AnIteratorOfAListOf<T>;
  200.     
  201. public:
  202.     AListOf() :
  203.         fListStorage(sizeof(T)) {}
  204.     
  205.     AListOf(SInt32 initialItems) :
  206.         fListStorage(sizeof(T), initialItems) {}
  207.     
  208.     AListOf(const AListOf<T>& copyFrom) :
  209.         fListStorage(copyFrom.fListStorage) {}
  210.     
  211.     //
  212.     // Simple list access
  213.     //
  214.     Boolean                    Empty() const                                { return fListStorage.Empty(); }
  215.     SInt32                    ItemsInList() const                            { return fListStorage.ItemsInList(); }
  216.  
  217.     //
  218.     // Primary list-manipulation and item access API:
  219.     //
  220.     AListOf<T>*                Clone() const                                { AListOf<T>* clonedList = new AListOf<T>(*this); return clonedList; }
  221.     
  222.     //
  223.     // Add an item to the list in no particular order (puts new
  224.     // item in using the fastest insertion available)
  225.     //
  226.     void                    Add(const T& valueToAdd)                    { fListStorage.Add((const char*)&valueToAdd); }
  227.     Boolean                    Remove(const T& valueToRemove)                { return fListStorage.Remove((const char*)&valueToRemove, CompareTwoElements); }
  228.     
  229.     //
  230.     // n.b.    Inserting N items at the beginning of the list is O(N^2)
  231.     //        Inserting N items at the end of the list is O(N)
  232.     //        Inserting N items at the end of the list and reversing their order is also O(N).
  233.     //    
  234.     void                    InsertAtBeginning(const T& valueToAdd)        { fListStorage.InsertAtBeginning((const char*)&valueToAdd); }
  235.     void                    InsertAtEnd(const T& valueToAdd)            { fListStorage.InsertAtEnd((const char*)&valueToAdd); }
  236.  
  237.     //
  238.     // n.b.    Removing N items from the beginning of the list is O(N^2)
  239.     //        Removing N items from the end of the list is O(N)
  240.     //
  241.     void                    RemoveFromBeginning()                        { fListStorage.RemoveFromBeginning(); }
  242.     void                    RemoveFromEnd()                                { fListStorage.RemoveFromEnd(); }
  243.  
  244.     //
  245.     // List accessors
  246.     //    
  247.     T                        FirstItem() const                            { T result; fListStorage.FirstItem((char*)&result); return result; }
  248.     T                        LastItem() const                            { T result; fListStorage.LastItem((char*)&result); return result; }
  249.  
  250.     //
  251.     // Misc list manipulation
  252.     //
  253.     void                    ReverseOrderOfList()                        { T tempStorage; fListStorage.ReverseOrderOfList((char*)&tempStorage); }
  254.     void                    MakeEmpty()                                    { fListStorage.MakeEmpty(); }
  255.         
  256.     //
  257.     // Synonyms, for those who care
  258.     //
  259.     void                    Push(const T& valueToPush)                    { this->InsertAtEnd(valueToPush); }
  260.     T                        TopOfStackValue() const                        { return this->LastItem(); }
  261.     T                        Pop()                                        { T temp = this->TopOfStackValue(); this->RemoveFromEnd(); return temp; }
  262.     
  263.     //
  264.     // Enqueueing and dequeueing N items is O(N*D), where D is the
  265.     // average depth of the queue.  This is O(N^2) for most uses.
  266.     // O(N) algorithms exist, but currently are not implemented, as
  267.     // they require leaving insertion gaps that either invalidate the
  268.     // format of our list, or needlessly complicate the access for
  269.     // all lists, even those not to be used as a queue.  If you
  270.     // really need a fast queue, write a queue class, don't use this
  271.     // template.
  272.     //
  273.     void                    Enqueue(const T& valueToQ)                    { this->InsertAtEnd(valueToQ); }
  274.     T                        TopOfQueueValue() const                        { return this->FirstItem(); }
  275.     T                        Dequeue()                                    { T temp = this->TopOfQueueValue(); this->RemoveFromBeginning(); return temp; }
  276.  
  277.     //
  278.     // Access locks for preemptive software.
  279.     //
  280.     // These locks should be kept for a minimum amount of time.
  281.     // Note that the methods above all call Lock/Relinquish as
  282.     // necessary.
  283.     //
  284.     //    -    LockForReading blocks until the active writer (if any)
  285.     //         relinquishes the write lock
  286.     //    -    LockForWriting blocks until the active writer and all
  287.     //         active readers (if any) relinquish their respective locks
  288.     //
  289.     // Every call to "Lock" must be (soon) balanced by a call to
  290.     // "Relinquish"; calling LockForReading multiple times is okay,
  291.     // as long as the calls to RelinquishReadLock balance the calls
  292.     // to LockForReading.
  293.     //
  294.     // IMPORTANT:  There can only be one writer, so you will
  295.     // block yourself forever (deadlock) if you try to LockForWriting.
  296.     // twice.  You will also block yourself forever if you call 
  297.     // LockForWriting followed by a call to LockForReading (or
  298.     // visa-versa).
  299.     //
  300.     // Therefore, calling the Lock routines directly is dangerous
  301.     //
  302.     void                    LockForReading() const                        { fListStorage.LockForReading(); }
  303.     void                    RelinquishReadLock() const                    { fListStorage.RelinquishReadLock(); }
  304.     void                    LockForWriting()                            { fListStorage.LockForWriting(); }
  305.     void                    RelinquishWriteLock()                        { fListStorage.RelinquishWriteLock(); }
  306.  
  307.     //
  308.     // WARNING:                The following routines are not pre-emptive safe if called directly,
  309.     //                        because the index values may change at any instant if another task
  310.     //                        modifies the list.
  311.     //
  312.     // Pre-emptive-safe alternatives:
  313.     //
  314.     // ItemAtIndex:            use an iterator and iter.Current()
  315.     // ReplaceItemAtIndex:    use an iterator and iter.SetCurrent()
  316.     // RemoveItemAtIndex:    use an iterator and iter.RemoveCurrent()
  317.     // IndexOfItem:            use an iterator and iter.AdvanceToItem()
  318.     //
  319.     // If for some reason you have a burning desire to NOT use an
  320.     // iterator, you may call these routines if you Lock/Relinquish
  321.     // this list appropriately, but you must do so carefully if you
  322.     // want to avoid deadlock.
  323.     //
  324.     T                        ItemAtIndex(SInt32 itemIndex) const                            { T result; fListStorage.ItemAtIndex(itemIndex, (char*)&result); return result; }
  325.     void                    ReplaceItemAtIndex(SInt32 itemIndex, const T& newValue)        { fListStorage.ReplaceItemAtIndex(itemIndex, (char*)&newValue); }
  326.     void                    RemoveItemAtIndex(SInt32 itemIndex)                            { fListStorage.RemoveItemAtIndex(itemIndex); }
  327.     SInt32                    IndexOfItem(const T& itemToFind, SInt32 startAt = 0) const    { return fListStorage.IndexOfItem((const char*)&itemToFind, CompareTwoElements, startAt); }
  328.  
  329. protected:
  330.     static Boolean            CompareTwoElements(const char* item1, const char* item2);
  331.  
  332.     //
  333.     // The ListStorage accessor is only used by AnIteratorOfAListOf
  334.     // to get the list storage to register itself with the list
  335.     // storage.
  336.     //
  337.     TListStorage&            ListStorage() { return fListStorage; }
  338.     
  339. private:
  340.     TListStorage            fListStorage;
  341. };
  342.  
  343.  
  344. //-------------------------------------------------------------------
  345. // AListOf<T>::CompareTwoElements
  346. //-------------------------------------------------------------------
  347. template <class T>
  348. Boolean AListOf<T>::CompareTwoElements(const char* item1, const char* item2)
  349. {
  350.     return ((T*)item1) == ((T*)item2);
  351. }
  352.  
  353.  
  354. //================================================================================
  355. // CLASS TAbstractListIterator
  356. //
  357. // Abstract base class for iterators, so that we may keep track of our
  358. // iterators in our list-storage class.
  359. //================================================================================
  360.  
  361. class TAbstractListIterator
  362. {
  363. public:
  364.     virtual void            NotifyItemAdded(SInt32 indexOfNewItem) = 0;
  365.     virtual void            NotifyItemRemoved(SInt32 indexOfItemRemoved) = 0;
  366.     virtual void            NotifyListDestroyed() = 0;
  367.  
  368. protected:
  369.     void                    RegisterWithList(TListStorage& list)        { list.AddIterator(this); }
  370.     void                    UnregisterWithList(TListStorage& list)        { list.RemoveIterator(this); }
  371. };
  372.  
  373. //================================================================================
  374. // TEMPLATE AnIteratorOfAListOf
  375. //================================================================================
  376.  
  377. template <class T> class AnIteratorOfAListOf : public TAbstractListIterator
  378. {
  379. public:
  380.     AnIteratorOfAListOf(AListOf<T>* inList, Boolean iterateBackwards = false) :
  381.         fList(inList),
  382.         fCurrentItem(0),
  383.         fRemovedCurrent(false),
  384.         fWeRemovedCurrent(false),
  385.         fIterateBackwards(iterateBackwards) { this->RegisterWithList(fList->ListStorage()); this->Reset(iterateBackwards); }
  386.     
  387.     ~AnIteratorOfAListOf() { this->UnregisterWithList(fList->ListStorage()); }
  388.     
  389.     void                    Reset(Boolean iterateBackwards = false);
  390.     
  391.     Boolean                    More() const;
  392.     UInt32                    ItemsRemainingToIterate() const;
  393.     void                    Next();
  394.     Boolean                    AdvanceToItem(const T&);
  395.     
  396.     const T&                Current() const;
  397.     void                    SetCurrent(const T& newValue);
  398.     void                    RemoveCurrent();
  399.     
  400.     virtual void            NotifyItemAdded(SInt32 indexOfNewItem);
  401.     virtual void            NotifyItemRemoved(SInt32 indexOfItemRemoved);
  402.     virtual void            NotifyListDestroyed();
  403.     
  404. private:
  405.     AListOf<T>*                fList;
  406.     SInt32                    fCurrentItem;
  407.     Boolean                    fRemovedCurrent;
  408.     Boolean                    fWeRemovedCurrent;
  409.     Boolean                    fIterateBackwards;
  410. };
  411.  
  412. //-------------------------------------------------------------------
  413. // AnIteratorOfAListOf<T>::Reset
  414. //-------------------------------------------------------------------
  415. template <class T>
  416. void AnIteratorOfAListOf<T>::Reset(Boolean iterateBackwards)
  417. {
  418.     if(fList != nil)
  419.     {
  420.         fList->LockForReading();
  421.         fIterateBackwards = iterateBackwards;
  422.         
  423.         if(fIterateBackwards)
  424.             fCurrentItem = fList->ItemsInList() - 1;
  425.         else
  426.             fCurrentItem = 0;
  427.         fList->RelinquishReadLock();
  428.     }
  429. }
  430.  
  431. //-------------------------------------------------------------------
  432. // AnIteratorOfAListOf<T>::More
  433. //-------------------------------------------------------------------
  434. template <class T>
  435. Boolean AnIteratorOfAListOf<T>::More() const
  436. {
  437.     Boolean moreItems = false;
  438.     
  439.     if(fList != nil)
  440.     {
  441.         fList->LockForReading();
  442.         moreItems = (fCurrentItem < fList->ItemsInList()) && (fCurrentItem >= 0);
  443.         fList->RelinquishReadLock();
  444.     }
  445.     
  446.     return moreItems;
  447. }
  448.  
  449. //-------------------------------------------------------------------
  450. // AnIteratorOfAListOf<T>::ItemsRemainingToIterate
  451. //-------------------------------------------------------------------
  452. template <class T>
  453. UInt32 AnIteratorOfAListOf<T>::ItemsRemainingToIterate() const
  454. {
  455.     UInt32 remainingItems = 0;
  456.     
  457.     if(fList != nil)
  458.     {
  459.         if(fIterateBackwards)
  460.             remainingItems = fCurrentItem + 1;
  461.         else
  462.         {
  463.             fList->LockForReading();
  464.             SInt32 totalItems = fList->ItemsInList();
  465.             fList->RelinquishReadLock();
  466.             
  467.             remainingItems = totalItems - fCurrentItem;
  468.         }
  469.     }
  470.     
  471.     return remainingItems;
  472. }
  473.  
  474. //-------------------------------------------------------------------
  475. // AnIteratorOfAListOf<T>::Next
  476. //-------------------------------------------------------------------
  477. template <class T>
  478. void AnIteratorOfAListOf<T>::Next()
  479. {
  480.     if(fList != nil)
  481.     {
  482.         //
  483.         // We must lock for reading so that someone does not
  484.         // come along and change the list (modifying our
  485.         // fCurrentItem) while we are updating our iteration
  486.         // state.
  487.         //
  488.         fList->LockForReading();
  489.         if((fRemovedCurrent == false) && (this->More()))
  490.         {
  491.             if(fIterateBackwards)
  492.                 --fCurrentItem;
  493.             else
  494.                 ++fCurrentItem;
  495.         }
  496.         fRemovedCurrent = false;
  497.         fList->RelinquishReadLock();
  498.     }
  499. }
  500.  
  501. //-------------------------------------------------------------------
  502. // AnIteratorOfAListOf<T>::AdvanceToItem
  503. //
  504. // n.b. If Current() == itemToFind, then this routine will NOT
  505. // advance anywhere, so cal Next() between calls to AdvanceToItem()
  506. // if you need to find every item of a given value in a list.
  507. //
  508. // fCurrentItem starts at the first item in the list, so this
  509. // routine wouldn't be able to find the first item in a list
  510. // if it skipped the current item before searching.
  511. //-------------------------------------------------------------------
  512. template <class T>
  513. Boolean AnIteratorOfAListOf<T>::AdvanceToItem(const T& itemToFind)
  514. {
  515.     Boolean foundItem = false;
  516.     
  517.     if(fList != nil)
  518.     {
  519.         if(fIterateBackwards == true)
  520.         {
  521.             DebugStr("\pAdvanceToItem doesn't work right when iterating backwards.  switching to forward iteration");
  522.             this->Reset(false); 
  523.         }
  524.         
  525.         fList->LockForReading();
  526.         SInt32 foundIndex = fList->IndexOfItem(itemToFind, fCurrentItem);
  527.         if(foundIndex != -1)
  528.         {
  529.             fCurrentItem = foundIndex;
  530.             foundItem = true;
  531.         }
  532.         fList->RelinquishReadLock();
  533.     }
  534.     
  535.     return foundItem;
  536. }
  537.  
  538. //-------------------------------------------------------------------
  539. // AnIteratorOfAListOf<T>::Current
  540. //-------------------------------------------------------------------
  541. template <class T>
  542. const T& AnIteratorOfAListOf<T>::Current() const
  543. {
  544.     T result;
  545.     
  546.     if(fList != nil)
  547.     {
  548.         //
  549.         // We must lock for reading so that someone does not
  550.         // change the list in between the time we access our
  551.         // field fCurrentItem and the time that ItemAtIndex
  552.         // returns.
  553.         //
  554.         fList->LockForReading();
  555.         result = fList->ItemAtIndex(fCurrentItem);
  556.         fList->RelinquishReadLock();
  557.     }
  558.     
  559.     return result;
  560. }
  561.  
  562. //-------------------------------------------------------------------
  563. // AnIteratorOfAListOf<T>::SetCurrent
  564. //-------------------------------------------------------------------
  565. template <class T>
  566. void AnIteratorOfAListOf<T>::SetCurrent(const T& newValue)
  567. {
  568.     if(fList != nil)
  569.     {
  570.         fList->LockForWriting();
  571.         fList->ReplaceItemAtIndex(fCurrentItem, newValue);
  572.         fList->RelinquishWriteLock();
  573.     }
  574. }
  575.  
  576. //-------------------------------------------------------------------
  577. // AnIteratorOfAListOf<T>::RemoveCurrent
  578. //-------------------------------------------------------------------
  579. template <class T>
  580. void AnIteratorOfAListOf<T>::RemoveCurrent()
  581. {
  582.     if(this->More())
  583.     {
  584.         //
  585.         // When we call 'RemoveItemAtIndex,' we
  586.         // will be called back and our fCurrentItem
  587.         // will be automatically updated, and
  588.         // fRemovedCurrent will be set to true.
  589.         //
  590.         // The same thing would happen if someone
  591.         // else removes our current item.
  592.         //
  593.         fList->LockForWriting();
  594.         fList->RemoveItemAtIndex(fCurrentItem);
  595.         fList->RelinquishWriteLock();
  596.         
  597.         fWeRemovedCurrent = true;
  598.     }
  599. }
  600.  
  601. //-------------------------------------------------------------------
  602. // AnIteratorOfAListOf<T>::NotifyItemAdded
  603. //-------------------------------------------------------------------
  604. template <class T>
  605. void AnIteratorOfAListOf<T>::NotifyItemAdded(SInt32 indexOfNewItem)
  606. {
  607.     //
  608.     // If an item is inserted before our current item,
  609.     // then we want to advance such that 'fCurrentItem'
  610.     // still points at the same item it did before the
  611.     // insertion happened.
  612.     //
  613.     if(indexOfNewItem <= fCurrentItem)
  614.         ++fCurrentItem;
  615. }
  616.  
  617. //-------------------------------------------------------------------
  618. // AnIteratorOfAListOf<T>::NotifyItemRemoved
  619. //-------------------------------------------------------------------
  620. template <class T>
  621. void AnIteratorOfAListOf<T>::NotifyItemRemoved(SInt32 indexOfItemRemoved)
  622. {
  623.     //
  624.     // If someone removes our current item, then
  625.     // we need to adjust for that fact.
  626.     //
  627.     if(indexOfItemRemoved == fCurrentItem)
  628.     {
  629.         //
  630.         // Immediately adjust 'fCurrentItem' so that
  631.         // it points to the next item, and remember
  632.         // that the current item was removed so that
  633.         // Next() will not advance again.
  634.         //
  635.         if(fIterateBackwards)
  636.             --fCurrentItem;
  637.         fRemovedCurrent = true;
  638.         fWeRemovedCurrent = false;
  639.     }
  640.     //
  641.     // If someone removes an item that is not our current
  642.     // item, then adjust 'fCurrentItem' such that it still
  643.     // points at the same item it did before the removal.
  644.     //
  645.     else if(indexOfItemRemoved < fCurrentItem)
  646.     {
  647.         --fCurrentItem;
  648.     }
  649. }
  650.  
  651. //-------------------------------------------------------------------
  652. // AnIteratorOfAListOf<T>::NotifyListDestroyed
  653. //-------------------------------------------------------------------
  654. template <class T>
  655. void AnIteratorOfAListOf<T>::NotifyListDestroyed()
  656. {
  657.     fList = nil;
  658. }
  659.  
  660. #endif
  661.